package com.bizmda.bizsip.converter.iso8583;

import cn.hutool.core.util.HexUtil;

import java.io.ByteArrayOutputStream;
import java.util.BitSet;

public class ByteBitUtil {
    public static byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        System.arraycopy(src, begin, bs, 0, count);
        return bs;
    }

    /**
     * 获取字节在内存中某一位的值,采用字符取值方式
     */
    public static Integer getBitByByte(byte b, int index) {
        if(index >= 8) { return null; }
        Integer val;
        String binStr = byte2Bin(b);
        val = Integer.parseInt(String.valueOf(binStr.charAt(index)));
        return val;
    }
    /**
     * 获取字节在内存中多位的值,采用字符取值方式(包含endIndex位)
     */
    public static Integer getBitByByte(byte b, int begIndex, int endIndex) {
        if(begIndex >= 8 || endIndex >= 8 || begIndex >= endIndex) { return null; }
        Integer val;
        String binStr = byte2Bin(b);
        val = Integer.parseInt(binStr.substring(begIndex, endIndex +1), 2);
        return val;
    }

    /**
     * 把单个字节转换成二进制字符串
     */
    public static String byte2Bin(byte b) {
        String zero = "00000000";
        String binStr = Integer.toBinaryString(b & 0xFF);
        if(binStr.length() < 8) {
            binStr = zero.substring(0, 8 -binStr.length()) + binStr;
        }
        return binStr;
    }
    /**
     * 把单个字节转换成二进制字符串
     */
    public static String byte2Bit(byte b) {
        return "" +(byte)((b >> 7) & 0x1) +
                (byte)((b >> 6) & 0x1) +
                (byte)((b >> 5) & 0x1) +
                (byte)((b >> 4) & 0x1) +
                (byte)((b >> 3) & 0x1) +
                (byte)((b >> 2) & 0x1) +
                (byte)((b >> 1) & 0x1) +
                (byte)((b) & 0x1);
    }

    /**
     * 二进制字符串转byte
     */
    public static byte convertBit2byte(String byteStr) {
        int re, len;
        if (null == byteStr) {
            return 0;
        }
        len = byteStr.length();
        if (len != 4 && len != 8) {
            return 0;
        }

        if (len == 8) {
            // 8 bit处理
            if (byteStr.charAt(0) == '0') {
                // 正数
                re = Integer.parseInt(byteStr, 2);
            } else {
                // 负数
                re = Integer.parseInt(byteStr, 2) - 256;
            }
        } else {
            // 4 bit处理
            re = Integer.parseInt(byteStr, 2);
        }
        return (byte) re;
    }
    /**
     * 将BitSet对象转化为ByteArray
     * @param bitSet
     * @return
     */
    public static byte[] bitSet2ByteArray(BitSet bitSet) {
        byte[] bytes = new byte[bitSet.size() / 8];
        for (int i = 0; i < bitSet.size(); i++) {
            int index = i / 8;
            int offset = 7 - i % 8;
            bytes[index] |= (bitSet.get(i) ? 1 : 0) << offset;
        }
        return bytes;
    }
    /**
     * 将ByteArray对象转化为BitSet
     * @param bytes
     * @return
     */
    public static BitSet byteArray2BitSet(byte[] bytes) {
        BitSet bitSet = new BitSet(bytes.length * 8);
        int index = 0;
        for (byte aByte : bytes) {
            for (int j = 7; j >= 0; j--) {
                bitSet.set(index++, (aByte & (1 << j)) >> j == 1);
            }
        }
        return bitSet;
    }
    /**
     * Creates a clone of the given byte array.
     */
    public static byte[] getClone(byte[] pHexBinary)
    {
        byte[] result = new byte[pHexBinary.length];
        System.arraycopy(pHexBinary, 0, result, 0, pHexBinary.length);
        return result;
    }

    /**
     * Converts the string <code>pValue</code> into an array of hex bytes.
     */
    public static byte[] hexStr2Bin(String pValue)
    {
        if ((pValue.length() % 2) != 0)
        {
            throw new IllegalArgumentException("A com.z.socket.common.util.HexBinary string must have even length.");
        }
        byte[] result = new byte[pValue.length() / 2];
        int j = 0;
        for (int i = 0; i < pValue.length();)
        {
            byte b;
            char c = pValue.charAt(i++);
            char d = pValue.charAt(i++);
            if (c >= '0' && c <= '9')
            {
                b = (byte) ((c - '0') << 4);
            } else if (c >= 'A' && c <= 'F')
            {
                b = (byte) ((c - 'A' + 10) << 4);
            } else if (c >= 'a' && c <= 'f')
            {
                b = (byte) ((c - 'a' + 10) << 4);
            } else
            {
                throw new IllegalArgumentException("Invalid hex digit: " + c);
            }
            if (d >= '0' && d <= '9')
            {
                b += (byte) (d - '0');
            } else if (d >= 'A' && d <= 'F')
            {
                b += (byte) (d - 'A' + 10);
            } else if (d >= 'a' && d <= 'f')
            {
                b += (byte) (d - 'a' + 10);
            } else
            {
                throw new IllegalArgumentException("Invalid hex digit: " + d);
            }
            result[j++] = b;
        }
        return result;
    }

    /**
     *
     * @param hexStr
     * @return byte[]
     */
    public static byte[] hexStr2Bin1(String hexStr) {
        if (hexStr == null || "".equals(hexStr)) {
            return null;
        }
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    /**
     * Converts the byte array <code>pHexBinary</code> into a string.
     */
    public static String bin2HexStr(byte[] pHexBinary)
    {
        StringBuilder result = new StringBuilder();
        for (byte b : pHexBinary) {
            byte c = (byte) ((b & 0xf0) >> 4);
            if (c <= 9) {
                result.append((char) ('0' + c));
            } else {
                result.append((char) ('A' + c - 10));
            }
            c = (byte) (b & 0x0f);
            if (c <= 9) {
                result.append((char) ('0' + c));
            } else {
                result.append((char) ('A' + c - 10));
            }
        }
        return result.toString();
    }
    public static String bin2HexStr1(byte[] buf)
    {
        StringBuilder sb = new StringBuilder();
        for (byte b : buf) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    public static String bcd2Str(byte[] b)
    {
        char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        StringBuilder sb = new StringBuilder(b.length * 2);
        for (byte value : b) {
            sb.append(hexDigits[((value & 0xF0) >>> 4)]);
            sb.append(hexDigits[(value & 0xF)]);
        }

        return sb.toString();
    }


    public static byte[] str2Bcd(String asc)
    {
        int len = asc.length();
        int mod = len % 2;
        if (mod != 0) {
            asc = "0" + asc;
            len = asc.length();
        }
        byte[] abt = new byte[len];
        if (len >= 2) {
            len /= 2;
        }
        byte[] bbt = new byte[len];
        abt = asc.getBytes();

        for (int p = 0; p < asc.length() / 2; p++)
        {
            int j;
            if ((abt[(2 * p)] >= 97) && (abt[(2 * p)] <= 122)) {
                j = abt[(2 * p)] - 97 + 10;
            }
            else
            {
                if ((abt[(2 * p)] >= 65) && (abt[(2 * p)] <= 90)) {
                    j = abt[(2 * p)] - 65 + 10;
                } else {
                    j = abt[(2 * p)] - 48;
                }
            }
            int k;
            if ((abt[(2 * p + 1)] >= 97) && (abt[(2 * p + 1)] <= 122)) {
                k = abt[(2 * p + 1)] - 97 + 10;
            }
            else
            {
                if ((abt[(2 * p + 1)] >= 65) && (abt[(2 * p + 1)] <= 90)) {
                    k = abt[(2 * p + 1)] - 65 + 10;
                } else {
                    k = abt[(2 * p + 1)] - 48;
                }
            }
            int a = (j << 4) + k;
            byte b = (byte)a;
            bbt[p] = b;
        }
        return bbt;
    }
    /**
     * 将String转成BCD码
     *
     * @param s
     * @return
     */
    public static byte[] str2Bcd1(String s) {

        if (s.length() % 2 != 0) {
            s = "0" + s;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        char[] cs = s.toCharArray();
        for (int i = 0; i < cs.length; i += 2) {
            int high = cs[i] - 48;
            int low = cs[i + 1] - 48;
            baos.write(high << 4 | low);
        }
        return baos.toByteArray();
    }
    public static String formatBin2Hex(byte[] data){

        StringBuilder result = new StringBuilder();

        int n = 0;

        for(byte b : data){

            if(n % 16 == 0) {
                result.append(String.format("%05X: ",n));
            }

            result.append(String.format("%02X ",b));

            n++;

            if (n % 16 != 0) {
                continue;
            }
            result.append("\n");

        }

        result.append("\n");

        return result.toString();

    }
    public static void main(String[] args)
    {
        String s1="30383330822000000200000004000000";
        String s2="303832303f2000003f00000004000000";
        System.out.println((s1));
        System.out.println(HexUtil.decodeHex(s2));
       /* String ab = "0AZaz~";
        byte a = 0;
        byte b = '0';
        byte[] bytes = {1,(byte) 0x31, (byte) 0x10};
        System.out.println("数字："+a+"，char："+String.format("%c",a)+",Integer.toHexString:"+Integer.toHexString(a));
        System.out.println("字符："+String.format("%c",b)+"，char："+",Integer.toHexString:"+Integer.toHexString(b));
        System.out.println(bcd2Str(bytes));

        System.out.println("[" + bin2HexStr(ab.getBytes()) + "]");*/
    }
}
